package net.bat.web.api;

import java.util.Date;
import java.util.List;
import java.util.Map;

import net.bat.advice.LogAspect;
import net.bat.dao.UserDAO;
import net.bat.dao.UserDAO.Action;
import net.bat.dto.LoginInfo;
import net.bat.dto.ResultDTO;
import net.bat.entity.Task;
import net.bat.entity.User;
import net.bat.repository.TaskDao;
import net.bat.rest.RestService;
import net.bat.service.account.AccountService;
import net.bat.service.account.ShiroDbRealm.ShiroUser;
import net.bat.service.task.TaskService;

import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;

@Controller
public class ApiController {
	@Autowired
	private UserDAO dao;
	@Autowired
	private TaskDao taskDao;
	@Autowired
	private TaskService taskService;

	@Autowired
	private AccountService accountService;
	@Autowired
	private RestService restService;

	/*---------------for User---------------------**/
	@RequestMapping(value = "/rest/User", method = RequestMethod.POST)
	@ResponseBody
	public User updateUser(@RequestBody Map<String, Object> rmap) throws Exception {
		User user = dao.load(User.class, rmap);
		if (user.getRegisterDate() == null) {
			user.setRegisterDate(new Date());
		}
		// 如果需要修改密码
		if (rmap.containsKey("plainPassword")) {
			accountService.entryptPassword(user);
		}
		dao.save(user);
		return user;
	}

	@RequestMapping(value = "/rest/User/{id}", method = RequestMethod.PUT)
	@ResponseBody
	public User updateUser(@PathVariable Long id, @RequestBody Map<String, Object> rmap) throws Exception {
		User user = dao.load(User.class, rmap);
		// 如果需要修改密码
		if (rmap.containsKey("plainPassword")) {
			accountService.entryptPassword(user);
		}
		dao.save(user);
		return user;
	}

	@RequestMapping(value = "/rest/User", method = RequestMethod.DELETE)
	@ResponseBody
	public <T> void removeUser(@RequestBody Map<String, Object> rmap) throws Exception {
		List ids = (List) rmap.get("ids");
		for (int i = 0; i < ids.size(); i++) {
			Long id = Long.parseLong(ids.get(i).toString());
			LogAspect.logOper("User", id, null, Action.REMOVE);
			accountService.deleteUser(id);
		}
	}

	/*---------------for Task---------------------**/
	// extjs调用rec.save时 add or update 都有可能
	@RequestMapping(value = "/rest/Task", method = RequestMethod.POST)
	@ResponseBody
	public <T> T updateTask(@RequestBody Map<String, Object> rmap) throws Exception {
		User user = new User(getCurrentUserId());
		rmap.put("user", user);
		return (T) restService.updateEntity("Task", rmap);
	}

	@RequestMapping(value = "/rest/Task", method = RequestMethod.GET)
	@ResponseBody
	public ResultDTO getTasks(@RequestParam(value = "page", required = true) int page,
			@RequestParam(value = "start", required = true) int start,
			@RequestParam(value = "limit", required = true) int limit,
			@RequestParam(value = "filter", required = false) String filter,
			@RequestParam(value = "sort", required = false) String sort) throws Exception {
		Page<Task> p = taskService.getTaskEntities(page, start, limit, filter, sort, getCurrentUserId());
		ResultDTO r = new ResultDTO();
		r.total = p.getTotalElements();
		r.data = p.getContent();
		return r;
	}

	/*---------------for command rest---------------------**/

	@SuppressWarnings({ "unchecked" })
	@RequiresPermissions("*:view")
	@RequestMapping(value = "/exists/{entity}", method = RequestMethod.GET)
	@ResponseBody
	public boolean exists(@PathVariable String entity, @RequestParam(value = "pn", required = true) String pn,
			@RequestParam(value = "pv", required = true) Object pv) throws Exception {
		return restService.exists(entity, pn, pv);
	}

	@SuppressWarnings({ "unchecked" })
	@RequiresPermissions("*:view")
	@RequestMapping(value = "/distinct/{entity}/{property}", method = RequestMethod.GET)
	@ResponseBody
	public ResultDTO<Object> distinct(@PathVariable String entity, @PathVariable String property,
			@RequestParam(value = "limit", required = false) int limit,
			@RequestParam(value = "kw", required = false) String kw,
			@RequestParam(value = "filter", required = false) String filter) throws Exception {
		return restService.disticnt(entity, property, kw, limit, filter);
	}

	@RequestMapping(value = "/auth", method = RequestMethod.POST)
	@ResponseBody
	public User authenticate(@RequestBody LoginInfo request) {
		return accountService.login(request);
	}

	@RequestMapping(value = "/rest/{entity}", method = RequestMethod.GET)
	@ResponseBody
	public ResultDTO getEntities(@PathVariable String entity, @RequestParam(value = "page", required = true) int page,
			@RequestParam(value = "start", required = true) int start,
			@RequestParam(value = "limit", required = true) int limit,
			@RequestParam(value = "filter", required = false) String filter,
			@RequestParam(value = "sort", required = false) String sort) throws Exception {
		return restService.getEntities(page, start, limit, filter, sort, entity);
	}

	@RequestMapping(value = "/rest/{entity}/{id}", method = RequestMethod.GET)
	@ResponseBody
	public <T> T getEntity(@PathVariable String entity, @PathVariable Long id) throws Exception {
		return (T) restService.getEntity(entity, id);
	}

	@RequestMapping(value = "/rest/{entity}/{id}", method = RequestMethod.PUT)
	@ResponseBody
	public <T> T updateEntity(@PathVariable String entity, @PathVariable Long id, @RequestBody Map<String, Object> rmap)
			throws Exception {
		return (T) restService.updateEntity(entity, id, rmap);
	}

	@RequestMapping(value = "/rest/{entity}", method = RequestMethod.POST)
	@ResponseBody
	public <T> T updateEntity(@PathVariable String entity, @RequestBody Map<String, Object> rmap) throws Exception {
		return (T) restService.updateEntity(entity, rmap);
	}

	@RequestMapping(value = "/rest/{entity}", method = RequestMethod.DELETE)
	@ResponseBody
	public <T> T removeEntity(@PathVariable String entity, @RequestBody Map<String, Object> rmap) throws Exception {
		List ids = (List) rmap.get("ids");
		return (T) restService.removeEntitys(entity, ids.toArray());
	}

	private String addFilter(String filter, String filter_add) {
		if (filter == null) {
			return "[" + filter_add + "]";
		} else {
			return "[" + filter_add + "," + filter.substring(1) + "]";
		}
	}

	private Long getCurrentUserId() {
		ShiroUser user = (ShiroUser) SecurityUtils.getSubject().getPrincipal();
		return user.id;
	}

}
